﻿using System.Collections.Concurrent;
using RpcHelper;
using RpcSync.Model;
using RpcSync.Service.Interface;
using RpcSync.Service.Node;

namespace RpcSync.Service.Service
{
    [RpcClient.Attr.ClassLifetimeAttr(RpcClient.Attr.ClassLifetimeType.单例)]
    internal class NodeService : INodeService
    {
        private readonly ConcurrentDictionary<string, INodeServer> _NodeServer = new ConcurrentDictionary<string, INodeServer>();

        private RootNode[] _EndNode = null;

        public void LoadServerNode(ServerGroup[] groups, SystemType[] sysTypes)
        {
            RootNode[] roots = sysTypes.ConvertAll(a => new RootNode
            {
                Dictate = a.TypeVal,
                Id = a.Id
            });
            roots.ForEach(a =>
            {
                if (!this._NodeServer.ContainsKey(a.Dictate))
                {
                    this._NodeServer.TryAdd(a.Dictate, new EndNodeServer(a));
                }
            });
            this._EndNode = roots;
            groups.ForEach(a =>
            {
                INodeServer node = new NodeServer(sysTypes.FindAll(b => b.GroupId == a.Id));
                this._NodeServer.AddOrUpdate(a.TypeVal, node, (c, b) => node);
            });
        }
        private void _AddDictateNode(DictateNode node, DictateNode[] nodes)
        {
            if (node.IsEndpoint)
            {
                return;
            }
            DictateNode[] lower = nodes.FindAll(a => a.ParentId == node.Id);
            if (lower.Length == 0)
            {
                return;
            }
            INodeServer t = new DictateNodeServer(lower.ConvertAll(b => b.Dictate), this);
            this._NodeServer.AddOrUpdate(node.Dictate, t, (c, b) => t);
        }
        public void LoadDictateNode(DictateNode[] nodes)
        {
            DictateNode[] root = nodes.FindAll(a => a.ParentId == 0);
            root.ForEach(a =>
            {
                _AddDictateNode(a, nodes);
            });
        }
        public RootNode[] GetRootNode()
        {
            return this._EndNode;
        }
        public void Load(string key, List<RootNode> dictates)
        {
            if (this._NodeServer.TryGetValue(key, out INodeServer node))
            {
                node.Load(dictates);
            }
        }
        public void Load(string key, List<long> sysTypeId)
        {
            if (this._NodeServer.TryGetValue(key, out INodeServer node))
            {
                node.Load(sysTypeId);
            }
        }
    }
}
